
#include <gtest/gtest.h>

#include "nane/lib/nane.h"
#include "nane/core/crt/filesystem.h"
#include "nane/SerializeSystem/SerializeSystem.h"
#include "nane/core/conversion_stdstring.h"
#include "nane/core/IO.h"

#include <cstdio>

void SerializeABC()
{
    printf( "::serializeABC\n" );
}

class ABC
{
public:
    ABC( int _x, float _y, const std::string& _z, bool _w )
        : x( _x )
        , y( _y )
        , z( _z )
        , w( _w )
    {

    }
        
    void Serialize( nane::ISerializationProtocol* _protocol )
    {
        _protocol->Serialize( "FieldX", x );
        _protocol->Serialize( "FieldY", y );
        _protocol->Serialize( "FieldZ", z.c_str() );
        _protocol->Serialize( "FieldW", w );
    }

    void Deserialize( nane::DeserializationProtocol<>* _protocol )
    {
        //_protocol->deserialize("FieldX", &x);
        _protocol->DeserializeMemberFunction("FieldX", &ABC::SetX, this);
        _protocol->Deserialize("FieldY", &y);
        _protocol->Deserialize("FieldZ", &z);
        _protocol->Deserialize("FieldW", &w);
    }

    void SetX( int _x )
    {
        x = _x;
    }

public:
    int x;
    float y;
    std::string z;
    bool w;
};

TEST( NaneTest, SerializeSystemCheck )
{
    ASSERT_TRUE( nane::Initialize() );

    nane::SerializeSystem serializeSystem;
    ASSERT_TRUE( serializeSystem.Initialize() );
    ABC abc( 5, 3.14f, "test_string", true );
    ABC abc2( 0, 0.0f, "none", false );
    nane::DeserializationProtocol<> protocol;
    protocol.DeserializeFunction("ABC", ::SerializeABC);
    abc2.Deserialize(&protocol);

    nane::WriteFilePtr writeFile = nane::FileSystem::OpenWriteFile("test_ini.ini");
    EXPECT_TRUE( writeFile != nane::NullPtr );
	
    unsigned char bom[] = {0xEF, 0xBB, 0xBF};
    char iniFileContent[] = "[ABC]\n"
                            "FieldX = 5 #hahaha\n"
                            "FieldY=3.140000000000\n"
                            "      FieldZ				=            				test_string\n"
                            "\n"
                            "\n"
                            "#\n"
                            "#\n"
                            "FieldW=true";

    nane::IO<nane::IOUnsafe>::Write(writeFile.Get(), bom);
    nane::IO<nane::IOUnsafe>::Write(writeFile.Get(), iniFileContent);

    nane::uint32 bufferSize = static_cast<nane::uint32>(writeFile->Size())/2;
    nane::byte* buffer = new nane::byte[bufferSize];

    writeFile = nane::NullPtr;
    nane::ReadFilePtr readFile = nane::FileSystem::OpenReadFile("test_ini.ini");
    EXPECT_TRUE( serializeSystem.Deserialize(readFile, &protocol, buffer, bufferSize) );

    EXPECT_EQ( 5, abc2.x );
    EXPECT_FLOAT_EQ( 3.14f, abc2.y );
    EXPECT_STREQ( "test_string", abc2.z.c_str() );
    EXPECT_EQ( true, abc2.w );
    //EXPECT_TRUE( serializeSystem->serialize( file, "ABC", &serializeABC, &abc ) );
    //file->close();
    //nane::FileSystem::releaseFile( file );
    serializeSystem.Shutdown();

    delete[] buffer;
    readFile = nane::NullPtr;

    nane::Shutdown();
}
